const fs = require('fs');
const _ = require('lodash');
const execa = require('execa');

const run = (bin, args, opts = {}) =>
  execa(bin, args, { stdio: 'inherit', ...opts });
function capitalize(name = '') {
  return name
    .split('-')
    .map((n) => _.capitalize(n))
    .join('');
}

/**
 * 把药导出的文件列表写入到一个文件中。
 *
 * @param {string[]} [files=[]] - 文件列表
 * @param {string} path - 要写入的文件路径
 * @param {string} excludeTemplate - 入口文件额外的字符串模板
 */
function writeExportFile(files, path, excludeTemplate = '', cb) {
  if (!files || !files.length) return;
  /** @type {string[]} */
  const data = [];
  /** @type {string[]} */
  const defaultExport = [];
  /** @type {string[]} */
  const pkgs = [];

  files.forEach((file) => {
    pkgs.push(file);
    defaultExport.push(
      `export { default as ${capitalize(file)} } from './${file}';`,
    );
    data.push(`export * from './${file}';`);
  });
  cb?.(pkgs);
  fs.writeFileSync(
    path,
    `${defaultExport.join('\n')}\n${data.join('\n')}\n${excludeTemplate}`,
  );
  run('prettier', ['--write', path]);
}

/**
 * 一个简单的nodejs脚本，用于处理组件库入口文件的export自动生成。
 *
 * @param {AutoExportParams} params
 *
 * @typedef {object} AutoExportParams
 * @property {string} libName - pkg的短名
 * @property {string} excludeTemplate - 入口文件额外的字符串模板
 * @property {string[]} [excludeFiles=[]] - 要排除导出的组件名列表
 * @property {boolean} writeExcludeFile - 是否写入排除文件到根目录
 */
function autoExport(params) {
  const {
    excludeFiles = [],
    excludeTemplate = '',
    libName = '',
    writeExcludeFile,
    cb,
  } = params;
  if (!libName) throw Error(`libName cannot be empty.`);
  const libPath = `./packages/${libName}`;
  const tempFiles = fs.readdirSync(`${libPath}/src`);

  writeExportFile(
    tempFiles
      .filter((name) => !name.includes('.'))
      .filter((file) => !excludeFiles.includes(file))
      .filter((file) => fs.existsSync(`${libPath}/src/${file}/style`)),
    `${libPath}/src/index.ts`,
    excludeTemplate,
    (pkgs) => cb?.(libPath, pkgs),
  );

  if (writeExcludeFile) {
    writeExportFile(
      tempFiles
        .filter((name) => !name.includes('.'))
        .filter((file) => excludeFiles.includes(file))
        .filter((file) => fs.existsSync(`${libPath}/src/${file}/style`)),
      `${libPath}/src/exclude.ts`,
    );
  }
}

exports.autoExport = () => {
  console.info(`\u001b[33m开始检测文件变动啦～\u001b[39m\n`);
  autoExport({
    libName: 'component',
    excludeFiles: ['date-picker', 'select'],
    writeExcludeFile: true,
    cb: (libPath, pkgs) => {
      const pkgPath = `${libPath}/src/pkg.ts`;
      fs.writeFileSync(
        pkgPath,
        `/** babel-plugin-pxx-import 判断来源 */
export default ${JSON.stringify(pkgs)}`,
      );
      run('prettier', ['--write', pkgPath]);
    },
  });
  autoExport({
    libName: 'web',
    excludeTemplate: `export * from '@pxxtech/component';`,
  });
  autoExport({
    libName: 'mobile',
    excludeFiles: ['mask', 'popup'],
    excludeTemplate: `export * from '@pxxtech/component';`,
  });
  console.info(`\u001b[33m文件变动检测完毕～\u001b[39m\n`);
};
